<?php
/**
 * Hoffman Framework
 *
 * LICENSE
 *
 * This source file is subject to the GNU LGPL 2.1 license that is bundled
 * with this package in the file license.txt.
 * It is also available through the world-wide-web at this URL:
 * http://creativecommons.org/licenses/LGPL/2.1
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to annop@thaicyberpoint.com so we can send you a copy immediately.
 *
 * @package    Hoffman
 * @author     Ford AntiTrust
 * @copyright  Copyright (c) 2008 Ford AntiTrust (http://www.thaicyberpoint.com/ford/blog)
 * @since      Version Rv 0.2
 * @license    http://creativecommons.org/licenses/LGPL/2.1
 *             GNU LGPL 2.1
 * @filesource
 */

if (!defined('INDEX'))
    die('No direct script access allowed.');

/**
 * Dispatcher
 *
 * Activities include loading and linking of the classes needed
 * to execute a program, optional machine code generation and dynamic
 * optimization of the program, and actual program execution.
 *
 * @package     Hoffman
 * @category    Dispatcher
 * @author      Ford AntiTrust
 * @version     SVN: $Id: Dispatcher.php 167 2010-02-18 10:32:16Z annop.s@gmail.com $
 * @link        http://www.thaicyberpoint.com/ford/blog/hmf
 */

/**
 * Create constant for check or show information HMF version
 */
define('HMF_VERSION', 'Rv 0.3');
/**
 * Sets the current active configuration setting of magic_quotes_runtime
 */
@set_magic_quotes_runtime(0);
/**
 * Create constant for page's create timer
 */
define("TIMER_CREATE_PAGE", array_sum(explode(chr(32), microtime())));
/**
 * Create config varieble
 */
$config = null;
/**
 * Create acl varieble
 */
$acl = null;
/**
 * Create viewsInformations varieble for store the View informations
 */
$viewsInformations = null;
/**
 * Create rounting varieble for store Rounting informations
 */
$rounting = null;
/**
 * @see Framework's path and configurations file
 */
require_once 'Paths.php';
/**
 * @see Bootstrap file
 */
require_once PATH_FILE_APPLICATION_BOOTSTRAP;
/**
 * @see config variable
 */
require_once PATH_FILE_APPLICATION_CONFIGURATIONS;
/**
 * @see viewsInformations variable
 */
require_once PATH_FILE_APPLICATION_VIEWS_INFORMATIONS;
/**
 * @see routing variable
 */
require_once PATH_FILE_APPLICATION_ROUTING;
/**
 * @see acl variable
 */
require_once PATH_FILE_APPLICATION_ACL;
/**
 * @see Zend_Loader
 */
require_once 'Zend/Loader.php';
/**
 * @see Zend_Session
 */
require_once 'Zend/Session.php';
/**
 * @see Zend_Registry
 */
require_once 'Zend/Registry.php';
/**
 * @see Zend_Version
 */
require_once 'Zend/Version.php';
/**
 * @see Hmf_Errors
 */
require_once 'Hmf/Errors.php';
/**
 * @see Hmf_Config
 */
require_once 'Hmf/Config.php';
/**
 * @see Hmf_Httppage
 */
require_once 'Hmf/Httppage.php';
/**
 * @see Hmf_View
 */
require_once 'Hmf/View.php';
/**
 * @see Hmf_Logs
 */
require_once 'Hmf/Logs.php';
/**
 * @see Hmf_Routing
 */
require_once 'Hmf/Routing.php';

try {

    /**
     * used Zend Loader Autoloader
     * Fix Notice : Zend_Loader::Zend_Loader::registerAutoload is deprecated as of 1.8.0
     *            : and will be removed with 2.0.0; use Zend_Loader_Autoloader
     */

    # Zend_Loader::registerAutoload();

    require_once 'Zend/Loader/Autoloader.php';
    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->setFallbackAutoloader(true);

} catch (Exception $e) {
    /**
     * Default Error Exception
     */
    Hmf_Errors::showError($e->getCode(), 'AutoLoader', $e->getMessage(), 'error');
}

/*
 * Check ENVIRONMENT constant from Bootstrap loader
 */
if (strcasecmp(ENVIRONMENT, "production") === 0) {

    /**
     * Register 'is_production' with true.
     */
    Zend_Registry::set('is_production', true);

    /**
     * Turn off all error reporting
     */
    @error_reporting(0);
} else {

    /**
     * Register 'is_production' with false.
     */
    Zend_Registry::set('is_production', false);

    /**
     * Report all errors except E_NOTICE
     */
    @error_reporting(E_ALL ^ E_NOTICE);

    /**
     * Check the Zend Framework installed to your system with Zend Framework 1.7 or below.
     */
    if (Zend_Version::compareVersion(HMF_USED_ZF) > 0) {
        Hmf_Errors::invalidZFVersion();
    }
}
try {
    /**
     * Process the config varieble and register the 'app_config' and 'app_locale' to Zend_Register in application
     */
    Hmf_Config::process($config);
} catch (Exception $e) {
    /**
     * Default Error Exception
     */
    Hmf_Errors::showError($e->getCode(), 'Process configuration', $e->getMessage(), 'error');
}
/**
 * delete config varieble
 */
unset($config);

/**
 * Load Default Hmf Helpers Functions
 */
if(Hmf_Config::getConfig('function.helpers.default')) {
    require_once 'Helpers.php';
}

/**
 * Load Extended Hmf Helpers Functions
 */
if(Hmf_Config::getConfig('function.helpers.extended')) {
    $extendedHelperArrayFile = Hmf_Config::getConfig('function.helpers.extended.load');
    foreach($extendedHelperArrayFile as $fileName) {
        if (file_exists(PATH_DIR_APPLICATION_HELPERS . '/'. $fileName . '.php')) {
            require_once PATH_DIR_APPLICATION_HELPERS . '/'. $fileName . '.php';
        } else {
            Hmf_Errors::missingExtendedHelpers($fileName);
        }

    }
}

/**
 * Filter data in QueryString
 */
Hmf_Httppage::FilterQuerystring();
/**
 * Register acl variable to 'acl' index in Zend_Registry
 */
Zend_Registry::set('acl', $acl);
/**
 * delete acl varieble
 */
unset($acl);
/*
 * Register viewsInformations variable to 'app_viewinfo' index in Zend_Registry
 */
Zend_Registry::set('app_viewinfo', $viewsInformations);
/**
 * delete viewsInformations variable
 */
unset($viewsInformations);
/*
 * Register rounting variable to 'rounting' index in Zend_Registry
 */
Zend_Registry::set('rounting', $rounting);
/**
 * delete rounting variable
 */
unset($rounting);
/**
 * Process the QueryString in $_GET['qs'] for handle to the controller and the action (with parameter)
 * and register output to 'routing_url' index in Zend_Registry
 */
Zend_Registry::set('routing_url', new Hmf_Routing($_GET['qs']));
try {
    /**
     * Get the data from routing_url index in Zend_Registry and set to routes variable
     */
    $routes = Zend_Registry::get('routing_url')->getRoutes();
    if (empty($routes[':controller']) or empty($routes[':action'])) {
        Hmf_Errors::routing();
    }
} catch (Exception $e) {
    /**
     * Default Error Exception
     */
    Hmf_Errors::showError($e->getCode(), 'Get Routes data', $e->getMessage(), 'error');
}
/**
 * Preifx name for controller class
 * @var string
 */
define('CONTROLLER_PREFIX_NAME', 'controller_');
/**
 * Regsiter path of controller file to controller_file in Zend_Registry index.
 */
Zend_Registry::set('controller_file', $routes[':controller'] . '.php');
/**
 * Regsiter name of controller class to controller_name in Zend_Registry index.
 */
Zend_Registry::set('controller_name', CONTROLLER_PREFIX_NAME . $routes[':controller']);
/**
 * Regsiter name of class method to action_name in Zend_Registry index.
 */
Zend_Registry::set('action_name', $routes[':action']);
/**
 * Regsiter args of class method to action_args in Zend_Registry index.
 */
Zend_Registry::set('action_args', (empty($routes[':args']) ? array() : $routes[':args']));
/**
 * delete routes variable
 */
unset($routes);
/**
 * define PATH_DIR_APPLICATION_CONTROLLERS_FILE for store path of application controller file
 */
define("PATH_DIR_APPLICATION_CONTROLLERS_FILE", PATH_DIR_APPLICATION_CONTROLLERS . '/' . Zend_Registry::get('controller_file'));
if (!file_exists(PATH_DIR_APPLICATION_CONTROLLERS_FILE)) {
    Hmf_Errors::missingControllerFile(Zend_Registry::get('controller_file'));
}
/**
 * @see Bootstrap_Controller
 */
require_once PATH_FILE_APPLICATION_BOOTSTRAP_CONTROLLER;
/**
 * @see Specified with controller class in just-in-time action
 */
require_once PATH_DIR_APPLICATION_CONTROLLERS_FILE;

if (!class_exists(Zend_Registry::get('controller_name'))) {
    Hmf_Errors::missingControllerClass(Zend_Registry::get('controller_name'));
}

try {
    /**
     * Lnitialize to class variable with ReflectionClass from controller name
     */
    $class = new ReflectionClass(Zend_Registry::get('controller_name'));

    /**
     * Begin check valid controller class
     * - Controller is subclass from Bootstrap_Controller
     * - Controller has __construct method
     * - Controller has action method with just-in-time action
     */
    if (!$class->isSubclassOf('Bootstrap_Controller')) {
        Hmf_Errors::classNotExtends('Bootstrap_Controller', Zend_Registry::get('controller_name'));
    }
    if (!$class->hasMethod('__construct')) {
        Hmf_Errors::missingConstructor();
    }
    if (!$class->hasMethod(Zend_Registry::get('action_name'))) {
        Hmf_Errors::missingAction(Zend_Registry::get('action_name'), Zend_Registry::get('controller_name'));
    }
    /**
     * End check valid controller class
     */

    /**
     * Lnitialize to method variable with ReflectionMethod from action name
     */
    $method = new ReflectionMethod(Zend_Registry::get('controller_name'), Zend_Registry::get('action_name'));

    /**
     * Check number of argument
     */
    if (($method->getNumberOfRequiredParameters() - count(Zend_Registry::get('action_args'))) > 0) {
        Hmf_Errors::missingArgs($method->getNumberOfRequiredParameters(), Zend_Registry::get('controller_name'), Zend_Registry::get('action_name'));
    }
    /**
     * Create View instance and register to view in Zend_Registry index.
     */
    Zend_Registry::set('view', new Hmf_View());
    /**
     * Create controller instance from class variable.
     */
    $objController = $class->newInstanceArgs();
    /**
     * Load controller constructor
     */
    $objController->loadFlowControllerConstructor();
    /**
     * Set default content-page with action_name from Zend_Register index to controller ojbect
     */
    $objController->useContentPage('index', Zend_Registry::get('action_name'));
    /**
     * Invoke Controller with argument
     */
    $controllerReturnValue = $method->invokeArgs($objController, Zend_Registry::get('action_args'));
    /**
     * TODO Check return invoke for Backward compatible with old controller style
     * and append data to content-page data (it slower than new style)
     * Remove Backward compatible soon.
     */
    if (!is_null($controllerReturnValue)) {
        Zend_Registry::get('view')->appendContentPageData('index', $controllerReturnValue);
    }

} catch (Exception $e) {
    /**
     * Default Error Exception
     */
    Hmf_Errors::showError($e->getCode(), 'Controller', $e->getMessage(), 'error');
}

try {
    /**
     * Render the content-page and master-page and send data to users.
     */
    Zend_Registry::get('view')->render($objController);
} catch (Exception $e) {
    /**
     * Default Error Exception
     */
    Hmf_Errors::showError($e->getCode(), 'View Render', $e->getMessage(), 'error');
}

try {
    /**
     * Store log for debug with memory usages
     */
    @Hmf_Logs::memUsage(Zend_Registry::get('controller_name'), Zend_Registry::get('action_name'), Zend_Registry::get('action_args'));
} catch (Exception $e) {
    /**
     * Default Error Exception
     */
    Hmf_Errors::showError($e->getCode(), 'Logs Memory Usages', $e->getMessage(), 'error');
}